#ifndef xpack_net_tls
#define xpack_net_tls
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::net_tls::inc
#include"define/base_type.hpp"
#include"macro/xhand_over.hpp"
#include"macro/xstruct.hpp"
#include"utils/bexx.hpp"
#include"meta/is_same.hpp"
#pragma pop_macro("xuser")

namespace mixc::net_tls::origin::tls{

    enum content_t : u08{
        handshake               = 22,
    };

    enum supported_version_t : u16{
        tls_v1                  = 0x0301,
        tls_v1p1                = 0x0302,
        tls_v1p2                = 0x0303,
        tls_v1p3                = 0x0304,
    };

    enum handshake_t : u08{
        client_hello            = 1,
        server_hello            = 2,
        new_session_ticket      = 4,
        end_of_early_data       = 5,
        encrypted_extensions    = 8,
        certificate             = 11,
        certificate_request     = 13,
        certificate_verify      = 15,
        finished                = 20,
        key_update              = 24,
        message_hash            = 254,
    };

    enum extension_t : u16{
        server_name                             = 0,
        supported_groups                        = 10,
        ec_point_format                         = 11,
        signature_algorithms                    = 13,
        application_layer_protocol_negotiation  = 16,
        padding                                 = 21,
        encrypt_then_mac                        = 22,
        extended_master_secret                  = 23,
        post_handshake_auth                     = 49,

        next_protocol_negotiation               = 13172,
    };

    // 对称加密算法
    enum cipher_t : u16{
        tls_aes_128_gcm_sha256          = 0x1301,
        tls_aes_256_gcm_sha384          = 0x1302,
        tls_chacha20_poly1305_sha256    = 0x1303,
        tls_aes_128_ccm_sha256          = 0x1304,
        tls_aes_128_ccm_8_sha256        = 0x1305,
    };

    // 签名 hash 算法
    enum signature_hash_t : u16{
        /* RSASSA-PKCS1-v1_5 algorithms */
        rsa_pkcs1_sha256        = 0x0401,
        rsa_pkcs1_sha384        = 0x0501,
        rsa_pkcs1_sha512        = 0x0601,

        /* ECDSA algorithms */
        ecdsa_secp256r1_sha256  = 0x0403,
        ecdsa_secp384r1_sha384  = 0x0503,
        ecdsa_secp521r1_sha512  = 0x0603,

        /* RSASSA-PSS algorithms with public key OID rsaEncryption */
        rsa_pss_rsae_sha256     = 0x0804,
        rsa_pss_rsae_sha384     = 0x0805,
        rsa_pss_rsae_sha512     = 0x0806,

        /* EdDSA algorithms */
        ed25519                 = 0x0807,
        ed448                   = 0x0808,

        /* RSASSA-PSS algorithms with public key OID RSASSA-PSS */
        rsa_pss_pss_sha256      = 0x0809,
        rsa_pss_pss_sha384      = 0x080a,
        rsa_pss_pss_sha512      = 0x080b,

        /* Legacy algorithms */
        rsa_pkcs1_sha1          = 0x0201,
        ecdsa_sha1              = 0x0203,
    };

    // 非对称加密算法
    enum supported_groups_t{
        /* Elliptic Curve Groups (ECDHE) */
        secp256r1               = 0x0017,
        secp384r1               = 0x0018,
        secp521r1               = 0x0019,
        x25519                  = 0x001D,
        x448                    = 0x001E,

        /* Finite Field Groups (DHE) */
        ffdhe2048               = 0x0100,
        ffdhe3072               = 0x0101,
        ffdhe4096               = 0x0102,
        ffdhe6144               = 0x0103,
        ffdhe8192               = 0x0104,
    };

    enum ec_point_format_t : u08{
        uncompressed                            = 0,
        ansiX962_compressed_prime               = 1,
        ansiX962_compressed_char2               = 2,
    };

    enum psk_key_exchange_modes_t : u08{
        psk_ke,
        psk_dhe_ke,
    };

    using be08                      = u08;
    using be16                      = inc::beu16;
    using be24                      = inc::beu24;
    using be16_cipher_t             = inc::bexx<cipher_t, 2>;
    using be16_signature_t          = inc::bexx<signature_hash_t, 2>;
    using be16_extension_t          = inc::bexx<extension_t, 2>;
    using be16_supported_groups_t   = inc::bexx<supported_groups_t, 2>;

    struct header{
        content_t               content;
        supported_version_t     version;
        be16                    bytes;
    };

    struct handshake_header{
        enum{
            random_length       = 32,
        };

        handshake_t             type;
        be24                    bytes;
        supported_version_t     version;
        be08                    random[random_length];
    };

    template<class bytes_t, class item_t, class next_t = void>
    struct handshake_filed{
        using the_t             = handshake_filed<bytes_t, item_t, next_t>;
        bytes_t                 bytes;
        item_t                  item[1];

        auto next_field(){
            if constexpr (inc::is_same<next_t, void>){
                return (the_t *)(u08p(this) + sizeof(bytes) + bytes);
            }
            else{
                return (next_t *)(u08p(this) + sizeof(bytes) + bytes);
            }
        }
    };


    struct handshake_extension_field;
    using handshake_compression_method  = handshake_filed<be08, be08, handshake_extension_field>;
    using handshake_cipher_suit         = handshake_filed<be16, be16_cipher_t, handshake_compression_method>;
    using handshake_session             = handshake_filed<be08, be08, handshake_cipher_suit>;


    // extension part =======================
    // TODO:
    // using handshake_server_name =

    using handshake_ec_point_format     = handshake_filed<be08, ec_point_format_t, handshake_extension_field>;
    using handshake_supported_groups    = handshake_filed<be16, be16_supported_groups_t, handshake_extension_field>;

    // TODO:
    // using handshake_next_protocol_negotiation =
    using handshake_alpn_entry          = handshake_filed<be08, char>;
    using handshake_alpn                = handshake_filed<be08, handshake_alpn_entry, handshake_extension_field>;

    // TODO:
    // using handshake_encrypt_then_mac =
    // using handshake_extended_master_secret =
    // using handshake_post_handshake_auth =
    using handshake_signature_suit      = handshake_filed<be16, be16_signature_t, handshake_extension_field>;
    using handshake_supported_version   = handshake_filed<be08, supported_version_t, handshake_extension_field>;

    using handshake_psk_key_exchange_modes
                                        = handshake_filed<be08, psk_key_exchange_modes_t, handshake_extension_field>;

    struct handshake_key_share_entry{
        supported_groups_t      group;
        be16                    bytes;
        be08                    item[1];

        auto next_field(){
            return (handshake_key_share_entry *)(this->item + bytes);
        }
    };

    using handshake_key_share           = handshake_filed<be16, handshake_key_share_entry, handshake_extension_field>;

    struct handshake_extension_field{
        using hepf  = handshake_ec_point_format;
        using hsg   = handshake_supported_groups;
        using ha    = handshake_alpn;
        using hss   = handshake_signature_suit;
        using hsv   = handshake_supported_version;
        using hpkem = handshake_psk_key_exchange_modes;

        be16_extension_t        type;
        be16                    bytes;
        
        union{
            hepf                ec_point_format;
            hsg                 supported_groups;   // 支持的非对称加密算法组
            ha                  alpn;               // 应用层协议名称
            hss                 signature_suit;
            hsv                 supported_version;
            hpkem               psk_key_exchange_mode;
        };
    };

    struct xxx{
        handshake_t             type;
        be24                    length;

        void handler(){
            switch(type) {
            case client_hello:          this->handler_client_hello();           break;
            case server_hello:          this->handler_server_hello();           break;
            case end_of_early_data:     this->handler_end_of_early_data();      break;
            case encrypted_extensions:  this->handler_encrypted_extensions();   break;
            case certificate_request:   this->handler_certificate_request();    break;
            case certificate:           this->handler_certificate();            break;
            case certificate_verify:    this->handler_certificate_verify();     break;
            case finished:              this->handler_finished();               break;
            case new_session_ticket:    this->handler_new_session_ticket();     break;
            case key_update:            this->handler_key_update();             break;
            };
        }

    private:
        void handler_client_hello(){

        }
        void handler_server_hello(){

        }
        void handler_end_of_early_data(){

        }
        void handler_encrypted_extensions(){

        }
        void handler_certificate_request(){

        }
        void handler_certificate(){

        }
        void handler_certificate_verify(){

        }
        void handler_finished(){

        }
        void handler_new_session_ticket(){

        }
        void handler_key_update(){

        }
    };
}

#endif

xexport_space(mixc::net_tls::origin)
